import type { CallbackDataParams, YAXisOption } from 'echarts/types/dist/shared'
import { type BaseBarLineScatterECOption, type TooltipFormatterMethod } from './ImportEcharts'
import type {
  ColorString,
  OrdinalRawValue,
  SymbolCallback,
  TextCommonOption
} from 'echarts/types/src/util/types.js'
import type { ECBarData, ECLineData, ECScatterData } from '../typing'
import type { PolarBarLabelPosition } from 'echarts/types/src/chart/bar/BarSeries.js'

/**
 * # 左右y轴配置
 */
export interface LeftRightYAxisOption {
  /**
   * # y轴名
   */
  name?: string
  /**
   * # y轴刻度后缀
   * ---
   * 默认值: 空字符串
   */
  stufix?: string
  /**
   * # 是否显示箭头
   * ---
   * 默认: false
   */
  showXArrow?: boolean
}
/**
 * # y轴配置
 */
export interface YAxisOption {
  /**
   * # y轴刻度颜色
   */
  color?: ColorString | ((value?: string | number, index?: number) => ColorString)
  /**
   * # 左侧y轴配置
   */
  leftYAxisOption?: LeftRightYAxisOption
  /**
   * # 右侧y轴配置
   * ---
   * 默认: undefined
   *
   * 值为 `undefined` 时，表示无需启用右侧 y 轴
   */
  rightYAxisOption?: LeftRightYAxisOption
}
/**
 * # x轴配置
 */
export interface XAxisOption {
  /**
   * # 刻度label颜色
   */
  color?: ColorString | ((value?: string | number, index?: number) => ColorString)
  /**
   * # x轴数据
   */
  xAxisData?: (
    | OrdinalRawValue
    | {
        value: OrdinalRawValue
        textStyle?: TextCommonOption
      }
  )[]
  /**
   * # 是否显示刻度
   * ---
   * 默认: false
   */
  showAxisTick?: boolean
  /**
   * # 刻度文本倾斜角度
   */
  rotate?: number
  /**
   * # 刻度文本格式化
   * ---
   * 
   * @example
   * ```js
   * function formatter(value, index){
   *  if (index % 2 === 0) {
        return `${value}`
      } else {
        // 换行显示
        return `\n${value}`
      }
   * }
   * ```
   */
  formatter?: string | ((val: unknown, idx: number) => string)
  /**
   * # 是否显示x轴箭头
   * ---
   * 默认: false
   */
  showArrow?: boolean
  /**
   * # 坐标轴显示名称
   */
  name?: string
}

/**
 * # 自定义echart配置
 */
export interface BarLineScatterChartOption {
  /**
   * # 自定义tooltip内容显示方法
   */
  tooltipFormatter?: TooltipFormatterMethod
  /**
   * # y轴配置
   */
  yAxisOption?: YAxisOption
  /**
   * # x轴配置
   */
  xAxisOption: XAxisOption
  /**
   * # 系列配置
   */
  seriesOptionArr: (SeriesOption | BarSeriesOption | LineSeriesOption)[]
  /**
   * 字体大小
   */
  fontSize?: number
}

export interface SeriesOption {
  /**
   * # 图表元件类型
   */
  type: 'bar' | 'line' | 'scatter'
  /**
   * # 系列名
   * ---
   * 更新数据时，需要通过该名称更新
   */
  name: string
  /**
   * # 图表元件数据
   */
  data?: ECBarData | ECLineData | ECScatterData
  /**
   * # 数据对应的y轴索引号
   * ---
   * 0或undefined: 表示对应左侧y轴
   *
   * 1: 表示对应右侧y轴
   */
  yAxisIndex?: number
  /**
   * # label位置. 默认: top
   * ---
   * - top: 显示在元件之上
   * - inside: 显示在元件之中
   * - bottom: 显示在元件之下
   */
  labelPosition?: PolarBarLabelPosition | 'outside'
  /**
   * # label颜色
   */
  labelColor?: ColorString | ((value?: string | number, index?: number) => ColorString)
  /**
   * # 是否显示label值
   * ---
   * 默认: true
   */
  showLabel?: boolean
  /**
   * 元件颜色（如：柱子颜色，折线上点的颜色）
   */
  itemColor?: ColorString | ((value?: string | number, index?: number) => ColorString)
}

export interface BarSeriesOption extends SeriesOption {
  /**
   * # 限制柱子最大宽度
   */
  barMaxWidth?: number
  /**
   * # 当柱子的系列大于等于2时，barGap用于设置不同系列之间柱子的间距
   * ---
   * -100% 会使两个系列的柱子的位置完全重合
   */
  barGap?: string
  /**
   * 柱子的堆叠名称。相同堆叠名的柱子会堆叠起来显示
   */
  stack?: string
}
export interface LineSeriesOption extends SeriesOption {
  /**
   * # 折线中数据点的图形
   * ---
   * 可选值: `cirlce`, `rect`, or custom path and image
   */
  symbol?: string | SymbolCallback<CallbackDataParams>
  /**
   * # 折线中数据点的图形的大小
   */
  symbolSize?: number
}

/**
 * # 构建 echarts 的 option
 * @param option 自定义配置
 * @returns
 */
export function buildBarLineScatterChartOption(
  option: BarLineScatterChartOption
): BaseBarLineScatterECOption {
  const { tooltipFormatter, yAxisOption = {}, xAxisOption, seriesOptionArr } = option
  const {
    color: xAxisColor,
    xAxisData,
    showAxisTick = false,
    rotate,
    formatter: axisLabelFormatter,
    showArrow: showXArrow = false,
    name
  } = xAxisOption
  const yAxis = buildYAxis(yAxisOption)
  const series = buildSeries(seriesOptionArr, yAxisOption)
  return {
    tooltip: {
      trigger: 'axis',
      formatter: tooltipFormatter
    },
    yAxis,
    xAxis: {
      type: 'category',
      name,
      nameTextStyle: {
        // 设置name距离x轴的距离
        padding: 40
      },
      data: xAxisData,
      axisLabel: {
        show: true,
        color: xAxisColor,
        rotate: rotate,
        formatter: axisLabelFormatter
      },
      axisTick: {
        show: showAxisTick
      },
      axisLine: {
        symbol: showXArrow ? ['none', 'arrow'] : undefined,
        /**
         * 设置箭头偏移量，否则箭头与柱子完全贴合在一起
         */
        symbolOffset: 10
      }
    },
    series
  }
}

/**
 * # 构建图表系列配置
 * @param optionArr 系列配置
 * @param yAxisOption y轴配置
 * @returns echart系列配置
 */
function buildSeries(
  optionArr: (SeriesOption | BarSeriesOption | LineSeriesOption)[],
  yAxisOption: YAxisOption
): BaseBarLineScatterECOption['series'] {
  const { leftYAxisOption, rightYAxisOption } = yAxisOption
  const leftStufix = leftYAxisOption?.stufix ?? ''
  const rightStufix = rightYAxisOption?.stufix ?? ''
  // @ts-ignore
  return optionArr.map((item) => {
    const {
      name,
      data,
      type,
      yAxisIndex,
      labelPosition = 'top',
      labelColor,
      showLabel = true,
      itemColor
    } = item
    const stufix = yAxisIndex === 1 ? rightStufix : leftStufix
    return {
      name,
      data,
      type,
      yAxisIndex,
      label: {
        show: showLabel,
        position: labelPosition,
        formatter: `{c}${stufix}`,
        color: labelColor
      },
      itemStyle: {
        color: itemColor
      },
      // @ts-ignore
      symbol: item.symbol,
      // @ts-ignore
      symbolSize: item.symbolSize,
      // @ts-ignore
      barGap: item.barGap,
      // @ts-ignore
      stack: item.stack,
      // @ts-ignore
      barMaxWidth: item.barMaxWidth
    }
  })
}
/**
 * # 构建y轴配置
 * @param option 自定义配置
 * @returns
 */
function buildYAxis(option: YAxisOption): YAXisOption[] {
  const { leftYAxisOption, rightYAxisOption, color } = option
  const arr: YAXisOption[] = []
  if (!leftYAxisOption) {
    const tmp = buildYAxisByOption({}, color)
    arr.push(tmp)
  } else {
    const tmp = buildYAxisByOption(leftYAxisOption, color)
    arr.push(tmp)
  }
  if (rightYAxisOption) {
    const tmp = buildYAxisByOption(rightYAxisOption, color)
    arr.push(tmp)
  }
  return arr
}
function buildYAxisByOption(
  leftRightYAxisOption: LeftRightYAxisOption,
  color?: ColorString | ((value?: string | number, index?: number) => ColorString)
): YAXisOption {
  const { name, stufix = '', showXArrow = false } = leftRightYAxisOption
  return {
    type: 'value',
    name,
    axisLabel: { formatter: `{value}${stufix}`, color },
    axisLine: {
      show: showXArrow,
      symbol: showXArrow ? ['none', 'arrow'] : undefined,
      /**
       * 设置箭头偏移量，否则箭头与柱子完全贴合在一起
       */
      symbolOffset: 10
    },
    max: (value) => {
      if (!Number.isNaN(value.max)) {
        if (value.max > 0) {
          return value.max * 1.3
        } else {
          return value.max / 1.3
        }
      } else {
        return value.max
      }
    },
    min: (value) => {
      if (!Number.isNaN(value.min)) {
        if (value.min > 0) {
          return 0
        } else {
          return value.min * 1.6
        }
      } else {
        return value.min
      }
    }
  }
}
